#ifndef __SLOTHTTPD_SERVER_T_HPP__
#define __SLOTHTTPD_SERVER_T_HPP__

#include <slothttpd/connection.hpp>
#include <slothttpd/aio/aio_operation.hpp>
#include <slothttpd/config/configuration.hpp>

#include <set>

#include <unistd.h>

#include <boost/asio.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/intrusive/list.hpp>

namespace slothttpd {

// TODO: rework this
class worker :
        public boost::intrusive::list_base_hook<boost::intrusive::link_mode<boost::intrusive::auto_unlink> >
{
public:
    worker();
    
    void stop();
    void kill();
    
private:
    void send_signal(int signo);
    
public:
    pid_t       pid;
};

class server
{
public:
    static boost::scoped_ptr<server> instance;
    static config::configuration_ptr conf;
    
    server(config::configuration_ptr cfg);
    
    boost::asio::io_service &get_service();
    void run();
    void stop();
    
private:
    static void set_process_title(const char *name);
    void spawn_worker();
    void master_cycle();
    void worker_cycle();
    
    void post_accept();
    void handle_accept(const boost::system::error_code& e);
    void handle_signal(int signo);
    
public:
    boost::asio::io_service io_service;
    boost::shared_ptr<aio::linux_aio_context> aio;
    
private:
    typedef boost::intrusive::list<worker, boost::intrusive::constant_time_size<false> > worker_list;
    
    bool                            is_master_;
    bool                            is_stopping_;
    worker_list                     workers_;
    boost::asio::ip::tcp::acceptor  acceptor_;
    boost::asio::signal_set         signals_;
    connection_ptr                  new_connection_;
};

} // namespace slothttpd

#endif
